跳到主要内容

摄像头(以 OV5647 为例)

本节以 OV5647 摄像头模组为例,说明在 NG4520 平台的开发适配流程,涵盖硬件前置、设备树、驱动编译、系统加载和调试等完整步骤。

Camera 架构与名词解释​

名词解释
ISP图像信号处理器,用于图像去噪、白平衡、色彩校正等。
Bayer即摄像头传感器,使用Bayer滤色阵列捕获图像。
CSI摄像头串行接口,用于摄像头与处理器之间的数据传输。
V4L2Linux内核的视频捕获和输出框架。
libargusNVIDIA提供的高级摄像头控制库。
Camera Core Library提供应用程序与内核模式V4L2驱动程序之间的控制和处理功能。
GStreamer开源的多媒体处理框架,用于音视频处理。
Host1xNVIDIA Tegra SoC中的主机接口控制器。
Aperture光圈控制,用于调节镜头的光圈大小。
UVCUSB视频类,用于USB摄像头的驱动程序。
VI视频输入模块,用于接收和处理视频数据。

Camera 软件架构说明

NVIDIA 平台支持两种 Camera 驱动架构:

  • Camera Core Library Interface:支持 ISP 访问和高级图像处理,应用层通过 libargus API 访问(如 nvgstcapture-1.0 工具)。
  • Direct V4L2 Interface:直接使用 V4L2 驱动,不支持 NVIDIA ISP。

建议开发时采用 Camera Core Library Interface,以便充分利用 NVIDIA ISP 能力。

OV5647 驱动适配流程​

前置条件​

  • 获取摄像头 I2C 地址及线序,确认 PWDN/RESET 引脚

  • 获取上电时序、外部时钟、支持分辨率/帧率、滤色器阵列类型(BGGR/GBRG/GRBG/RGGB)

  • 确认连接接口及 tegra_sinterface 对应关系(如 NG452X 平台 cam0=serial_c)

本例基于 Jetson Orin NX,硬件连接接口为 cam0。

设备树配置​

  • 创建设备树 Overlay 文件,路径示例如下:

    Linux_for_Tegra/source/hardware/nvidia/t23x/nv-public/overlay/tegra234-p3767-camera-p3768-ov5647.dts
  • tegra-camera-platform 节点配置,配置视频流端口及连接关系,示例:

    tegra-capture-vi  {
    num-channels = <1>;
    ports {
    #address-cells = <1>;
    #size-cells = <0>;
    vi_port1: port@1 {
    reg = <0>;
    rbpcv2_ov5647_vi_in1: endpoint {
    port-index = <2>;
    bus-width = <2>;
    remote-endpoint = <&rbpcv2_ov5647_csi_out1>;
    };
    };
    };
    };
  • I2C 设备节点配置

    配置摄像头参数(I2C 地址、模式、时钟、分辨率等):

    rbpcv2_ov5647_c@36 {
    reset-gpios = <&gpio CAM0_RST GPIO_ACTIVE_HIGH>;
    pwdn-gpios = <&gpio CAM1_PWDN GPIO_ACTIVE_HIGH>;
    compatible = "ovti,ov5647";
    /* I2C device address */
    reg = <0x36>;
    /* V4L2 device node loation */
    devnode = "video0";
    /* Physical dimensions of sensor */
    physical_w = "3.670";
    physical_h = "2.740";
    sensor_model = "ov5647";
    use_sensor_mode_id = "true";

    clocks = <&bpmp TEGRA234_CLK_EXTPERIPH2>,
    <&bpmp TEGRA234_CLK_PLLP_OUT0>;
    clock-names = "extperiph2", "pllp_grtba";
    mclk = "extperiph2";
    clock-frequency = <24000000>;

    mode0 { /* ov5647_MODE0_1920x1080_30FPS */
    mclk_khz = "25000";
    num_lanes = "2";
    // lane_polarity = "4";
    tegra_sinterface = "serial_c";
    phy_mode = "DPHY";
    discontinuous_clk = "yes";
    dpcm_enable = "false";
    cil_settletime = "0";
    active_w = "1920";
    active_h = "1080";
    mode_type = "bayer";
    pixel_phase = "bggr";
    csi_pixel_bit_depth = "10";
    readout_orientation = "90";
    line_length = "2416";
    inherent_gain = "1";
    mclk_multiplier = "3.6669";
    pix_clk_hz = "81666663";
    gain_factor = "16";
    framerate_factor = "1000000";
    exposure_factor = "1000000";
    min_gain_val = "16";
    max_gain_val = "128";
    step_gain_val = "1";
    default_gain = "16";
    min_hdr_ratio = "1";
    max_hdr_ratio = "1";
    min_framerate = "30000000"; /* 30.0 fps */
    max_framerate = "30000000"; /* 30.0 fps */
    step_framerate = "1";
    default_framerate = "45000000"; /* 30.0 fps */
    min_exp_time = "60"; /* us */
    max_exp_time = "30000"; /* us */
    step_exp_time = "1";
    default_exp_time = "10000"; /* us */
    embedded_metadata_height = "0";
    };

    ........................

    ports {
    #address-cells = <1>;
    #size-cells = <0>;
    port@0 {
    reg = <0>;
    rbpcv2_ov5647_out1: endpoint {
    status = "okay";
    port-index = <1>;
    bus-width = <2>;
    remote-endpoint = <&rbpcv2_ov5647_csi_in1>;
    };
    };
    };

    };
  • 端口绑定配置

    • 通过 remote-endpoint 连接摄像头、CSI 和 VI 模块,确保视频流通路完整。

      tegra-capture-vi  {
      num-channels = <1>;
      ports {
      #address-cells = <1>;
      #size-cells = <0>;
      vi_port1: port@1 {
      reg = <0>;
      rbpcv2_ov5647_vi_in1: endpoint {
      port-index = <2>;
      bus-width = <2>;
      remote-endpoint = <&rbpcv2_ov5647_csi_out1>;
      };
      };
      };
      };

      host1x@13e00000 {
      nvcsi@15a00000 {
      num-channels = <1>;
      #address-cells = <1>;
      #size-cells = <0>;
      csi_chan1: channel@1 {
      reg = <0>;
      ports {
      #address-cells = <1>;
      #size-cells = <0>;
      csi_chan1_port0: port@0 {
      reg = <0>;
      rbpcv2_ov5647_csi_in1: endpoint@2 {
      port-index = <2>;
      bus-width = <2>;
      remote-endpoint = <&rbpcv2_ov5647_out1>;
      };
      };
      csi_chan1_port1: port@1 {
      reg = <1>;
      rbpcv2_ov5647_csi_out1: endpoint@3 {
      remote-endpoint = <&rbpcv2_ov5647_vi_in1>;
      };
      };
      };
      };
      };
      };
  • Overlay Makefile 配置,在 overlay/Makefile 添加:

    dtbo-y += tegra234-p3767-camera-p3768-ov5647.dtbo
  • 编译生成 dtbo:

    make dtbs

驱动开发与编译​

  • 添加驱动源码

    • 路径示例:drivers/media/i2c/ov5647.c
    • 推荐基于 nv_ov5693.c 修改。
    • 主要实现:
      • tegracam_device_register 注册驱动
      • 填充以下结构体:
        • tc_dev->sensor_ops(上电、下电、读写寄存器、模式设置、流控制等)
        • tc_dev->v4l2sd_internal_ops(如 open/s_stream)
        • tc_dev->tcctrl_ops(增益、曝光、帧率控制等)
    static struct tegracam_sensor_ops ov5647_sensor_ops = {
    .power_on = ov5647_power_on,
    .power_off = ov5647_power_off,
    .write_reg = ov5647_write_reg,
    .read_reg = ov5647_read_reg,
    .set_mode = ov5647_set_mode,
    .start_streaming = ov5647_start_streaming,
    .stop_streaming = ov5647_stop_streaming,
    .sensor_init = ov5647_sensor_init,
    };

    这些函数的具体实现需要根据 OV5647 的数据手册和相关文档进行编写。

    • 添加寄存器表头文件

      • 路径示例:drivers/media/i2c/ov5647_modes_tbls.h
      • 包含各分辨率、曝光等寄存器配置表,需与设备树 mode 顺序保持一致。
      static struct v4l2_subdev_internal_ops ov5647_subdev_internal_ops = {
      .open = ov5647_open,
      };
  • 驱动 Makefile 配置,在 drivers/media/i2c/Makefile 添加:

    obj-m += ov5647.o
  • 编译生成内核模块:

    make modules

系统适配与加载​

拷贝文件

  • 将编译生成的 .dtbo 和 ov5647.ko 拷贝到目标设备(如 NG4520):
cd Linux_for_Tegra/source

scp ./kernel-devicetree/generic-dts/dtbs/tegra234-p3767-camera-p3768-ov5647.dtbo milesight@192.168.60.3:/home/milesight
scp ./kernel-devicetree/generic-dts/dtbs/tegra234-p3767-camera-p3768-ov5647.dtbo milesight@192.168.60.3:/home/milesight

驱动安装

  • 拷贝ov5647.ko到modules目录下,并执行depmod加载驱动
sudo cp ./ov5647.ko  /usr/lib/modules/5.15.148-tegra/updates/drivers/media/i2c/

depmod
  • 拷贝 .dtbo 到 /boot,通过 config-by-hardware.py 工具加载。

  • 完成后,重启开发板即可。

调试与验证流程​

  1. 设备树加载验证

    • 检查 extlinux.conf 是否加载了 .dtbo:

      cat /boot/extlinux/extlinux.conf

    • 检查设备树节点是否生效:

      cat /proc/device-tree/tegra-camera-platform/modules/module1/drivernode0/sysfs-device-tree

  2. 驱动加载验证

    • 检查驱动模块:

      lsmod | grep ov5647 sudo dmesg | grep ov5647

    • 检查 I2C 设备匹配:

      sudo i2cdetect -y -r 9

  3. 摄像头功能测试

    • 运行 nvgstcapture-1.0,检查分辨率与模式匹配、无报错。

    • 检查视频流链路:

      sudo media-ctl -p -d /dev/media0

参考​

Sensor Software Driver Programming

ov5647_driver/ov5647.c at main · mkm684/ov5647_driver


如需适配其它型号摄像头,建议参考原厂数据手册及 NVIDIA 官方开发文档,步骤基本一致。